<!DOCTYPE html>
<html lang="zh-CN">

<head>
  <meta charset="UTF-8">
  <meta name="viewport" content="width=device-width, initial-scale=1.0">
  <title>Document</title>
</head>

<body>
  <h2>自己实现事件总线</h2>
  <button class="on">注册事件</button>
  <button class="emit">触发事件</button>
  <button class="off">移除事件</button>
  <button class="once-on">一次性事件注册</button>
  <button class="once-emit">一次性事件触发</button>
  <script>
    class HMEmmiter {
      // 保存注册事件的实例私有属性
      #handlers = {}
      // 注册事件
      $on(event, callback) {
        // 是否已经注册过事件
        if (this.#handlers[event] === undefined) {
          // 没注册过,设置初始值,[]
          this.#handlers[event] = []
        }
        // 注册过继续push
        this.#handlers[event].push(callback)
      }

      // 触发事件
      $emit(event, ...args) {
        // 取出保存的事件[]
        const funcs = this.#handlers[event]
        // 挨个触发,并传入参数
        funcs.forEach(callback => {
          callback(...args)
        })
      }

      // 移除事件
      $off(event) {
        // event对应的回调函数数组设置为空即可
        this.#handlers[event] = []
      }
      // 一次性事件 注册了以后,只能触发一次
      $once(event, callback) {
        // 触发之后,清空,移除
        this.$on(event, (...args) => {

          // 执行callback
          callback(...args)
          // 移除注册的event事件
          this.$off(event)
        })
      }
    }

    // 简化 querySelector调用
    function qs(selector) {
      return document.querySelector(selector)
    }

    // 测试事件总线
    const myBus = new HMEmmiter()
    // 注册事件
    qs('.on').addEventListener('click', () => {
      myBus.$on('event1', () => { console.log('event1-func1') })
      myBus.$on('event1', () => { console.log('event1-func2') })
      myBus.$on('event2', () => { console.log('event2-func') })
      myBus.$on('event3', () => { console.log('event3-func') })
      myBus.$on('event4', (food, drink) => {
        console.log('event4-func')
        console.log('food:', food)
        console.log('drink:', drink)
      })
    })
    // 触发事件
    qs('.emit').addEventListener('click', () => {
      myBus.$emit('event4', '西兰花炒蛋', '西兰花汁')
      // myBus.$emit('event3')
    })
    // 移除事件
    qs('.off').addEventListener('click', () => {
      myBus.$off('event4')
    })
    // 一次性事件注册
    qs('.once-on').addEventListener('click', () => {
      console.log('注册了一次性事件')
      myBus.$once('once-func', (vegetable, meat) => {
        console.log('once-func-执行')
        console.log('vegetable:', vegetable)
        console.log('meat:', meat)
      })
    })
    // 一次性事件触发
    qs('.once-emit').addEventListener('click', () => {
      console.log('触发了一次性事件')
      myBus.$emit('once-func', '花菜', '牛肉')
    })
  </script>
</body>

</html>